package com.ww.springboot.boot.thread.study.base.lock.demo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 描述：lock condition 的关系及阻塞 唤醒的实现理解
 *
 * lock 有一个同步队列
 * condition 有一个等待队列
 *          await() 会释放资源并将线程节点设置为条件节点 将waitStatus设置为-2;
 *          signal() 会将相应的节点唤醒(错误) 会唤醒等待队列中的首节点,无法指定具体线程的环境 从等待队列移到同步队列中 并将waitStatus 设置为 -1
 *          signal() 不代表立马获取到锁 只是将其加入到同步队列中 自旋等待获取锁
 *
 *
 *
 * waitStatue
 * -1 唤醒
 * -2 条件
 * 0 默认值
 * -3 ??
 *
 * lock 与condition都相当于是工具载体  而线程才是真正核心的东西
 *
 *
 * @author 🧑 ‍wanwei
 * @since 2022-08-06 10:43
 */
public class AqsDemo3 {

    private static ReentrantLock lock = new ReentrantLock();

    private static Condition condition = lock.newCondition();
    private static Condition condition2 = lock.newCondition();

    private static int state = 1;

    public static void main(String[] args) {


        new Thread(() -> {
            test();
        }).start();

        new Thread(() -> {
            test2();
        }).start();
    }

    private static void test() {
        System.out.println("lock 1");
        lock.lock();
        System.out.println("lock 1 获取锁");
        try {
            while (true) {
                System.out.println("lock 1 " + "state:" + state);
                Thread.sleep(1000);
                if (state == 1) {
                    state = 2;
                    condition2.await();
                } else {
                    state = 1;
                    condition.signal();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    private static void test2() {
        System.out.println("lock 2");
        lock.lock();
        System.out.println("lock 2 获取锁");
        try {
            while (true) {
                System.out.println("lock 2 " + "state:" + state);
                Thread.sleep(1000);
                if (state == 2) {
                    state = 1;
                    condition2.signal();
                } else {
                    state = 2;
                    condition.await();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
